package com.zdp.applet.service;

import com.zdp.applet.rabbit.producer.ItemSpecProducer;
import com.zdp.applet.remote.OrderRemoteServer;
import com.zdp.common.constant.ApiConstant;
import com.zdp.common.domain.bo.SubmitItemSpecBO;
import com.zdp.common.domain.bo.SubmitOrderBO;
import com.zdp.common.domain.rabbit.FreezeStockMessage;
import com.zdp.common.domain.vo.StockVo;
import com.zdp.common.exception.ParameterException;
import com.zdp.common.result.ResultInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author sesshomaru
 * @date 2021/7/10 22:25
 */
@Slf4j
@Service
public class OrderService {

    @Autowired
    private ItemSpecService itemSpecService;

    @Autowired
    private ItemSpecProducer itemSpecProducer;

    @Autowired
    private OrderRemoteServer orderRemoteServer;

    @Transactional(rollbackFor = Exception.class)
    public String createOrder(SubmitOrderBO submitOrderBO) {
        List<SubmitItemSpecBO> orderItemSpecs = new ArrayList<>();
        boolean freezeStockSuccess= false;
        List<String> freezeStockItemSpecIds = new ArrayList<>();
        try {
            // 1. 扣减库存
            // 获取本次订单购买的所有商品规格以及个数
             orderItemSpecs = submitOrderBO.getItemSpecs();
            if (CollectionUtils.isEmpty(orderItemSpecs)) return "请选择需要购买的商品";
            for (SubmitItemSpecBO submitItemSpecBO : orderItemSpecs) {
                // 从缓存中扣减库存,如果存在库存不足或者其他异常则会向外抛出异常导致整个下单业务回滚，并且在catch代码块中恢复成下单操作前库存的数据
                StockVo stockVo = itemSpecService.freezeStockFromRemain(submitItemSpecBO.getItemSpecId(), submitItemSpecBO.getBuyCounts());
                freezeStockItemSpecIds.add(stockVo.getItemSpecId());
            }
            // 表示redis中的库存数已经被扣减了
            freezeStockSuccess = true;
            // 调用远端服务进行下单
            ResultInfo resultInfo = orderRemoteServer.create(submitOrderBO);
            if (resultInfo.getCode() != ApiConstant.SUCCESS_CODE) throw new ParameterException(500, "调用订单服务下单失败");
            // 模拟其他业务发生异常
            long timeMillis = System.currentTimeMillis();
            if ((timeMillis & 1) == 1) throw new ParameterException(500, "后续异常..........");
            // TODO 下单成功的后续操作如发送延迟消息校验订单超时
            // 异步更新数据库中的库存信息
            orderItemSpecs.forEach(orderItemSpec -> {
                itemSpecProducer.sendFreezeStockMessage(convertFreezeStockMessage(orderItemSpec));
            });
            // TODO 删除购物车中心的商品
            return "place an order success";
        } catch (Exception e) {
            // 如果扣减成功发生异常需归还冻结的库存
            if (freezeStockSuccess) {
                for (SubmitItemSpecBO submitItemSpecBO : orderItemSpecs) {
                    log.info("所有库存扣减成功发生异常需归还冻结的库存");
                    itemSpecService.unFreezeStockToRemain(submitItemSpecBO.getItemSpecId(), submitItemSpecBO.getBuyCounts());
                }

                // 归还已被扣减乘客库存
            } else {
                for (String freezeStockItemSpecId : freezeStockItemSpecIds) {
                    for (SubmitItemSpecBO submitItemSpecBO : orderItemSpecs) {
                        if (freezeStockItemSpecId.equals(submitItemSpecBO.getItemSpecId())) {
                            log.info("部分库存扣减成功发生异常需归还冻结的库存");
                            itemSpecService.unFreezeStockToRemain(submitItemSpecBO.getItemSpecId(), submitItemSpecBO.getBuyCounts());
                        }
                    }
                }
            }

           /* for (SubmitItemSpecBO submitItemSpecBO : orderItemSpecs) {
                itemSpecService.removeRedisStock(submitItemSpecBO.getItemSpecId());
            }*/
            log.error("下单失败", e);
            // 删除缓存恢复库存数据
            if (e instanceof ParameterException) {
                throw e;
            }
            throw new ParameterException(500, "下单失败，请稍后重试");
        }
    }

    private FreezeStockMessage convertFreezeStockMessage(SubmitItemSpecBO submitItemSpecBO) {
        FreezeStockMessage freezeStockMessage = new FreezeStockMessage();
        BeanUtils.copyProperties(submitItemSpecBO, freezeStockMessage);
        freezeStockMessage.setNumber(submitItemSpecBO.getBuyCounts());
        return freezeStockMessage;
    }
}
